//
//  mcast_service_process.cpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2013-2014 Razvan Coca (razvan dot coca at  gmail dot com)
// This is mostly generated code. Generator is distributed under GPL. Edit it to suit your needs.
// 



#include "mcast_service_process.hpp"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>

#include "patterns/command.hpp"
#include "patterns/handlers.hpp"

#include "logging/logging.hpp"

namespace pcmd=patterns::command;
namespace phdl=patterns::handlers;
namespace ba=boost::asio;
namespace bs=boost::system;
namespace bt=boost::posix_time;

#include "components/defs/util_types.hpp"
#include "components/defs/server_processor.hpp"
#include "components/service/mcast_service_process.hpp"
#include "components/network/setup_mcast.hpp"

namespace components{
namespace service{


bool mcast_service_process::cancel()
{

    try{
        bool retcode=true;
        LOG(WARNING)<<name_<<"::"<<__FUNCTION__;
        retcode &= (recv_client_request_ && recv_client_request_->cancel());
        retcode &= (server_send_reply_ && server_send_reply_->cancel());
        op_recv_client_request=nullptr;
        return retcode;
    }
    catch(std::exception &e){
        LOG(WARNING)<<name_<<"::"<<__FUNCTION__<<":"<<e.what();
        return false;
    }


}

boost::shared_ptr<mcast_service_process> mcast_service_process::create(ba::io_service& ios,udp_endpoint_t& local_if,udp_endpoint_t& mgroup,int ttl,crypto_buf_t& iv,crypto_buf_t& key,stats_message_server_processor& message_processor)
{

    return boost::shared_ptr<mcast_service_process>(new mcast_service_process(ios,local_if,mgroup,ttl,iv,key,message_processor));
}

void mcast_service_process::handle_recv_client_request(const bs::error_code& ec,const crypto_error& eec)
{


    LOG(INFO)<<name_<<"::"<<__FUNCTION__<<"["<<eec.GetWhat()<<"]";

    if(!phdl::is_error(eec))
    {
        LOG(INFO)<<__FUNCTION__<<":ec:\t"<<ec ;

    }

    //server_send_reply_ && server_send_reply_->cancel();


}

void mcast_service_process::handle_server_send_reply(const bs::error_code& ec,const crypto_error& eec)
{


    LOG(INFO)<<name_<<"::"<<__FUNCTION__<<"["<<eec.GetWhat()<<"]";

    if(!phdl::is_error(ec))
    {
        LOG(INFO)<<__FUNCTION__<<":ec:\t"<<ec ;
        pcmd::invoke(op_recv_client_request);
    }
    else
    {
        LOG(ERROR)<<__FUNCTION__<<":aborting service due to error:"<<ec;
        cancel();
    }



}

void mcast_service_process::init_components()
{

    if(!recv_client_request_) recv_client_request_ = components::protocol::recv_client_request::create(ios_,msocket_,iv_,key_,message_processor_);
    if(!server_send_reply_) server_send_reply_ = components::protocol::server_send_reply::create(ios_,iv_,key_,message_processor_,msocket_,mgroup_);
}

mcast_service_process::mcast_service_process(ba::io_service& ios,udp_endpoint_t& local_if,udp_endpoint_t& mgroup,int ttl,crypto_buf_t& iv,crypto_buf_t& key,stats_message_server_processor& message_processor)
    :ios_(ios), local_if_(local_if), mgroup_(mgroup), ttl_(ttl), iv_(iv), key_(key), message_processor_(message_processor),msocket_(ios_)
{

    name_=std::string(__FUNCTION__);
    DLOG(INFO)<<name_<<"()";
    setup_mcast_socket(msocket_,local_if_,mgroup_,ttl_);

}

mcast_service_process::~mcast_service_process()
{
    DLOG(INFO)<<name_<<"::"<<__FUNCTION__<<std::endl;
    try{
        teardown_mcast_socket(msocket_,mgroup_);
    }
    catch(std::exception const& e)
    {
        LOG(ERROR)<<"Leaving multicast group error:"<<e.what();
    }

}
}//end namespace service
}//end namespace components

